home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************
- * *
- * This code is developed by Adam Li. This software is an *
- * implementation of a part of one or more MPEG-4 Video tools as *
- * specified in ISO/IEC 14496-2 standard. Those intending to use this *
- * software module in hardware or software products are advised that its *
- * use may infringe existing patents or copyrights, and any such use *
- * would be at such party's own risk. The original developer of this *
- * software module and his/her company, and subsequent editors and their *
- * companies (including Project Mayo), will have no liability for use of *
- * this software or modifications or derivatives thereof. *
- * *
- * Project Mayo gives users of the Codec a license to this software *
- * module or modifications thereof for use in hardware or software *
- * products claiming conformance to the MPEG-4 Video Standard as *
- * described in the Open DivX license. *
- * *
- * The complete Open DivX license can be found at *
- * http://www.projectmayo.com/opendivx/license.php . *
- * *
- **************************************************************************/
-
- /*************************************************************************
- *
- * convert.cpp, image format conversion functions
- *
- * Copyright (C) 2000 DivX Networks
- *
- * Adam Li
- *
- * DivX Advance Research Center <darc@projectmayo.com>
- *
- ************************************************************************/
-
- // This includes the functions that converts the format of the image before
- // it is passed to the encore.
-
- #include "stdafx.h"
- #include "codec.h"
-
-
- int codec::getImageType(BITMAPV4HEADER *bmpinfohdr)
- {
- // return image type codes if the image is managable
- switch (bmpinfohdr->bV4V4Compression) {
- case BI_RGB:
- // if (bmpinfohdr->bV4BitCount == 16) return 16;
- if (bmpinfohdr->bV4BitCount == 24) return 17;
- if (bmpinfohdr->bV4BitCount == 32) return 18;
- return 0;
-
- case FOURCC_UYVY:
- return 32;
-
- case FOURCC_YUY2:
- case FOURCC_YUYV:
- case FOURCC_V422:
- return 33;
-
- case FOURCC_YVYU:
- return 34;
-
- case FOURCC_YV12:
- return 64;
-
- case FOURCC_I420:
- case FOURCC_IYUV:
- return 65;
-
- default:
- return 0;
- }
- }
-
-
- void codec::convertImage(void *imageIn, void *imageOut, long type, long x_dim, long y_dim)
- {
- switch (type) {
- case 16:
- case 17:
- case 18:
- convertRGB(imageIn, imageOut, type, x_dim, y_dim);
- return;
-
- case 32:
- case 33:
- case 34:
- convertYUV422(imageIn, imageOut, type, x_dim, y_dim);
- return;
-
- case 64:
- case 65:
- convertYUV420(imageIn, imageOut, type, x_dim, y_dim);
- return;
-
- default:
- return;
- }
- }
-
-
- /************************************************************************
- *
- * int convertRGB (void *bmp, void *yuv, long type, long x_dim, long y_dim)
- *
- * Purpose : It takes a 24-bit RGB bitmap and convert it into
- * YUV (4:2:0) format
- *
- * Input : x_dim the x dimension of the bitmap
- * y_dim the y dimension of the bitmap
- * bmp pointer to the buffer of the bitmap
- * yuv pointer to the YUV structure
- *
- * Output : 0 OK
- * 2 memory allocation error
- *
- ************************************************************************/
-
- static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
- static float RGBYUV01684[256], RGBYUV03316[256];
- static float RGBYUV04187[256], RGBYUV00813[256];
-
- # define MAX(a,b) (((a) > (b)) ? (a) : (b))
- # define CLIP(a,i,s) (((a) > (s)) ? (s) : MAX(a,i))
-
- int codec::convertRGB (void *bmp, void *yuv, long type, long x_dim, long y_dim)
- {
- static int init_done = 0;
-
- long i, j, size, stride;
- unsigned char *r, *g, *b;
- unsigned char *y, *u, *v;
- unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
- unsigned char *y_buffer, *u_buffer, *v_buffer;
- unsigned char *sub_u_buf, *sub_v_buf;
-
- if (init_done == 0)
- {
- InitLookupTable();
- init_done = 1;
- }
-
- // check to see if x_dim and y_dim are divisible by 2
- if ((x_dim % 2) || (y_dim % 2)) return 1;
- size = x_dim * y_dim;
-
- if (type == 17) stride = 3;
- else if (type == 18) stride = 4;
-
- // allocate memory
- y_buffer = (unsigned char *)yuv;
- sub_u_buf = y_buffer + size;
- sub_v_buf = y_buffer + size * 5 / 4;
- u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
- v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
- if (!(u_buffer && v_buffer))
- {
- if (u_buffer) free(u_buffer);
- if (v_buffer) free(v_buffer);
- return 2;
- }
-
- b = (unsigned char *)bmp;
- y = y_buffer;
- u = u_buffer;
- v = v_buffer;
-
- // convert RGB to YUV
- for (j = 0; j < y_dim; j ++)
- {
- y = y_buffer + (y_dim - j - 1) * x_dim;
- u = u_buffer + (y_dim - j - 1) * x_dim;
- v = v_buffer + (y_dim - j - 1) * x_dim;
-
- for (i = 0; i < x_dim; i ++) {
- g = b + 1;
- r = b + 2;
- *y = (unsigned char)CLIP (( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]), 0, 255.f);
- *u = (unsigned char)CLIP ((- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128), 0, 255.f);
- *v = (unsigned char)CLIP (( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128), 0, 255.f);
- b += stride;
- y ++;
- u ++;
- v ++;
- }
- }
-
- // subsample UV
- for (j = 0; j < y_dim/2; j ++)
- {
- psu = sub_u_buf + j * x_dim / 2;
- psv = sub_v_buf + j * x_dim / 2;
- pu1 = u_buffer + 2 * j * x_dim;
- pu2 = u_buffer + (2 * j + 1) * x_dim;
- pv1 = v_buffer + 2 * j * x_dim;
- pv2 = v_buffer + (2 * j + 1) * x_dim;
- for (i = 0; i < x_dim/2; i ++)
- {
- *psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;
- *psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;
- psu ++;
- psv ++;
- pu1 += 2;
- pu2 += 2;
- pv1 += 2;
- pv2 += 2;
- }
- }
-
- free(u_buffer);
- free(v_buffer);
-
- return 0;
- }
-
-
- void codec::InitLookupTable()
- {
- int i;
-
- for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
- for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
- for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
- for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
- for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
- for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
- for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
- }
-
-
- /************************************************************************
- *
- * int convertYUV422 (void *bmp, void *yuv, long type, long x_dim, long y_dim)
- *
- * Purpose : It takes a YUV422 image and convert it into YUV (4:2:0) format
- *
- * Input : x_dim the x dimension of the bitmap
- * y_dim the y dimension of the bitmap
- * yuv422 pointer to the buffer of the yuv422 image
- * yuv pointer to the YUV structure
- *
- * Output : 0 OK
- *
- ************************************************************************/
-
- int codec::convertYUV422 (void *yuv422, void *yuv, long type, long x_dim, long y_dim)
- {
- unsigned char *line1, *line2;
- unsigned char *y1, *y2, *u, *v;
-
- long w, h, size;
-
- size = x_dim * y_dim;
-
- h = y_dim / 2;
- line1 = (unsigned char *)yuv422; // points to the first line
- line2 = (unsigned char *)yuv422 + x_dim * 2; // points to the second line
- y1 = (unsigned char *)yuv;
- y2 = (unsigned char *)yuv + x_dim;
- u = (unsigned char *)yuv + size;
- v = u + size / 4;
-
- switch (type) {
- case 32: // UYVY
- while (h --) {
- w = x_dim / 2;
- while (w --) {
- *(u) = (unsigned char)(((int)*(line1 ) + (int)*(line2 )) / 2);
- *(v) = (unsigned char)(((int)*(line1 + 2) + (int)*(line2 + 2)) / 2);
- *(y1) = *(line1 + 1);
- *(y1+1) = *(line1 + 3);
- *(y2) = *(line2 + 1);
- *(y2+1) = *(line2 + 3);
-
- u ++;
- v ++;
- y1 += 2;
- y2 += 2;
- line1 += 4;
- line2 += 4;
- }
-
- y1 += x_dim;
- y2 += x_dim;
- line1 += x_dim * 2;
- line2 += x_dim * 2;
- }
- break;
-
- case 33: // YUYV YUY2 V422
- while (h --) {
- w = x_dim / 2;
- while (w --) {
- *(u) = (unsigned char)(((int)*(line1 + 1) + (int)*(line2 + 1)) / 2);
- *(v) = (unsigned char)(((int)*(line1 + 3) + (int)*(line2 + 3)) / 2);
- *(y1) = *(line1 );
- *(y1+1) = *(line1 + 2);
- *(y2) = *(line2 );
- *(y2+1) = *(line2 + 2);
-
- u ++;
- v ++;
- y1 += 2;
- y2 += 2;
- line1 += 4;
- line2 += 4;
- }
-
- y1 += x_dim;
- y2 += x_dim;
- line1 += x_dim * 2;
- line2 += x_dim * 2;
- }
- break;
-
- case 34: // YVYU
- while (h --) {
- w = x_dim / 2;
- while (w --) {
- *(v) = (unsigned char)(((int)*(line1 + 1) + (int)*(line2 + 1)) / 2);
- *(u) = (unsigned char)(((int)*(line1 + 3) + (int)*(line2 + 3)) / 2);
- *(y1) = *(line1 );
- *(y1+1) = *(line1 + 2);
- *(y2) = *(line2 );
- *(y2+1) = *(line2 + 2);
-
- u ++;
- v ++;
- y1 += 2;
- y2 += 2;
- line1 += 4;
- line2 += 4;
- }
-
- y1 += x_dim;
- y2 += x_dim;
- line1 += x_dim * 2;
- line2 += x_dim * 2;
- }
- break;
-
- default:
- break;
- }
-
- return 0;
- }
-
- /************************************************************************
- *
- * int convertYUV420 (void *bmp, void *yuv, long type, long x_dim, long y_dim)
- *
- * Purpose : It takes a YUV420 image and convert it into YUV (4:2:0) format
- *
- * Input : x_dim the x dimension of the bitmap
- * y_dim the y dimension of the bitmap
- * yuv420 pointer to the buffer of the yuv422 image
- * yuv pointer to the YUV structure
- *
- * Output : 0 OK
- *
- ************************************************************************/
-
- int codec::convertYUV420 (void *yuv420, void *yuv, long type, long x_dim, long y_dim)
- {
- long size;
- unsigned char *temp, *p1, *p2;
-
- if (type == 65) return 0; // I420 IYUV no conversion needed
-
- // type == 64 YV12
- size = x_dim * y_dim;
- temp = (unsigned char *)malloc(size / 4);
- if (temp == NULL) return 1;
-
- p1 = (unsigned char *)yuv420 + size;
- p2 = p1 + size / 4;
-
- memcpy(temp, p1, size / 4);
- memcpy(p1, p2, size / 4);
- memcpy(p2, temp, size / 4);
-
- return 0;
- }
-
-
-
-